﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CarbonExchange.Bll
{
    public class AmeeProfileItemProperty
    {
        internal AmeeProfileItemProperty(Types type, string name, string path)
        {
            this.Name = name;
            this.Path = path;
            this.DataType = type;
        }

        internal AmeeProfileItemProperty(string path, object value)
        {
            this.Path = path;
            if (value is string)
            {
                this.DataType = Types.String;
                this.Value = value;
            }
            else if (value is decimal)
            {
                this.DataType = Types.Decimal;
                this.Value = value;
            }
            else if (value is int)
            {
                this.DataType = Types.Integer;
                this.Value = value;
            }
            else if (value is bool)
            {
                this.DataType = Types.Boolean;
                this.Value = value;
            }
            else if (value != null)
            {
                throw new NotImplementedException(string.Format("Data Type '{0}' specified for '{1}' not implimented. Please do so.", value.GetType().ToString(), path));
            }
            else if (value == null)
            {
                throw new NotImplementedException(string.Format("Data Type specified for '{0}' not implimented and value is null. Please do so.", path));
            }
        }

        internal AmeeProfileItemProperty(string type, string name, string value, string path)
        {
            this.Name = name;
            this.Path = path;
            if (type.ToUpper() == "STRING" || type.ToUpper() == "TEXT")
            {
                DataType = Types.String;
                SetValue(value);
            }
            else if (type.ToUpper() == "INTEGER")
            {
                DataType = Types.Integer;
                SetValue(value);
            }
            else if (type.ToUpper() == "DECIMAL")
            {
                DataType = Types.Decimal;
                SetValue(value);
            }
            else if (type.ToUpper() == "BOOLEAN")
            {
                DataType = Types.Boolean;
                SetValue(value);
            }
            else
            {
                throw new NotImplementedException(string.Format("Data Type '{0}' not implimented. Please do so.", type));
            }
        }

        public enum Types
        {
            Null,
            String,
            Integer,
            Decimal,
            Boolean
        }

        internal void SetValue(object value)
        {
            Value = value;
        }

        internal void SetValue(string value)
        {
            switch (DataType)
            {
                case Types.String:
                    this.Value = value;
                    break;
                case Types.Integer:
                    this.Value = string.IsNullOrEmpty(value) ? new int?() : int.Parse(value);
                    break;
                case Types.Decimal:
                    this.Value = string.IsNullOrEmpty(value) ? new decimal?() : decimal.Parse(value);
                    break;
                case Types.Boolean:
                    this.Value = string.IsNullOrEmpty(value) ? new bool?(): bool.Parse(value);
                    break;
                default:
                    throw new NotImplementedException(string.Format("Data Type '{0}' not implimented. Please do so.", DataType.ToString()));
            }
        }



        public Types DataType { get; private set; }
        public string Name { get; internal set; }
        public object Value { get; private set; }
        public string Path { get; private set; }

        public T GetValue<T>()
        {
            if (this.Value == null)
            {
                return default(T);
            }
            else
            {
                try
                {
                    return (T)this.Value;
                }
                catch (InvalidCastException)
                {
                    throw new InvalidCastException(string.Format("Failed to cast object '{0}' with type '{1}' to type '{2}' for property '{3}'", this.Value, this.Value.GetType(), typeof(T), this.Name));
                }
            }
        }

        internal string GetAmeeValue()
        {
            switch (DataType)
            {
                case Types.String:
                    return (string)Value;
                case Types.Integer:
                    return ((int?)Value).ToString();
                case Types.Decimal:
                    return ((decimal?)Value).ToString();
                case Types.Boolean:
                    return ((bool?)Value).ToString().ToLower();
                default:
                    throw new NotImplementedException(string.Format("Data Type '{0}' not implimented. Please do so.", DataType.ToString()));
            }
        }
     }
}
